function createHashHistory(){
  //这里之所以要维护一个stack, 就是因为hash改变时 无法像 pushState(原生)一样 传递state（但hash改变也是会添加历史记录）
  const stack = [];

  let currentIndex = -1;
  let action;//最新的动作
  let state;//这是最新的状态 //比列表往详情页跳, 如果列表查询时带了详情的数据, 这里就可以将其放在state里 传递给 详情页; 或则跳转到一个受保护的页面需要登录 于是又跳转到了登录页 但登录以后要自动返回该页面 这个时候就可以在跳往登录页时带上一个state, 里面记录着from(跳转到登录页前的path)
  let listeners = [];
  function listen(listener){
    listeners.push(listener);
    return function(){//unlisten
      listeners = listeners.filter(l=>l!==listener);
    }
  }
  function go(n){
    action = 'POP';
    currentIndex += n;
    const nextLocation = stack[currentIndex];
    state = nextLocation.state;
    window.location.hash = nextLocation.pathname;
  }
  function goBack(){
    go(-1);
  }
  function goForward(){
    go(1);
  }
  const hashChange = () => {
    const pathname = window.location.hash.slice(1);
    Object.assign(history, {action, location: {pathname, state}});
    if (
      !action/*←说明是初始化,即调用createHashHistory这个函数时,会执行window.location.hash=初始值,往stack里放一层*/
      || action === 'PUSH'
    ) {
      stack[++currentIndex] = history.location;
      //↑ 不能直接 stack.push
      //因为假设 page1->page2->page3, 然后你回退到page2, 然后再前往一个新的page4, 你应该用page4覆盖page3, 而不是将page4放在page3后面
      //这里的index总是对的, 因为我们这里的hashHistory自己封装了go方法 而不是采用原生的, 比如go(-1)时 即goBack, 会在里面自动将index-1
    } else if (action === 'REPLACE') {
      stack[currentIndex] = history.location;
    }
    listeners.forEach(listener => listener(history.location,action)); //触发的是Router里的 this.setState, 也就是会让Router重新渲染
  };
  window.addEventListener('hashchange',hashChange);
  function push(pathname,nextState){
    action = 'REPLACE';
    if(typeof pathname === 'object'){
      state = pathname.state;
      pathname= pathname.pathname;
    }else{
      state = nextState;
    }
    window.location.hash = pathname; //给hash赋值的时候 不需要加# 会自动带上
  }
  function replace(pathname,nextState){
    action = 'PUSH';
    if(typeof pathname === 'object'){
      state = pathname.state;
      pathname= pathname.pathname;
    }else{
      state = nextState;
    }
    window.location.hash = pathname; //给hash赋值的时候 不需要加# 会自动带上
  }
  const history = {
    action: 'POP',//默认是POP, 当前最后一个动作是什么动作 (push PUSH, goBack、goForward、go POP)
    go,
    goBack,
    goForward,
    push,
    replace,
    listen,
    location:{pathname: '/',state:undefined},
  }

  if(window.location.hash){
    hashChange();
    //不直接 window.location.hash = window.location.hash.slice(1) 的原始是
    //防止刷新页面时 出现不正确加载对应页面的问题 (相同的hash跳到相同的hash(即刷新) 是不会触发onHashChange的)
  }else {
    window.location.hash = '/'; //  window.location.hash = '/' ---> https://www.xxx.com/#/ (原地址为https://www.xxx.com,则会加上#/);  window.location.hash = '', 如果原地址没有带#, 则不会加上, 但如果原地址带了#, 也不会去掉
    //↑ 此时会往stack里push第一层
  }

  return history;

  //todo 这里没有适配 prompt, 但createBrowseHistory里适配了 可以参考一下
}

export default createHashHistory;
